package com.khyr.Service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.wxpay.sdk.WXPayUtil;
import com.khyr.Dao.*;
import com.khyr.Service.OrderService;
import com.khyr.entity.*;
import com.khyr.feign.UserFeign;
import com.khyr.utils.HttpClient;
import com.khyr.utils.SnowflakeIdGenerator;
import com.khyr.vo.OrderChargeRequestVo;
import com.khyr.vo.R;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author 宋一恒
 * @version 1.0
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Value("${weixin.appid}")
    private String appId;

    @Value("${weixin.mch_id}")
    private String mchId;

    @Value("${weixin.api_key}")
    private String apiKey;

    @Value("${weixin.notify_url}")
    private String notifyUrl;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HisOrderChargeItemDao hisOrderChargeItemDao;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private CareOrderItemDao careOrderItemDao;

    @Autowired
    private CareOrdersDao careOrdersDao;

    @Override
    public R<Map> createNavite(String orderNo) {
        log.info("开始创建支付订单：{}", orderNo);
        //根据订单号查询出订单信息
        QueryWrapper<HisOrderCharge> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderNo);
        HisOrderCharge order = orderDao.selectOne(queryWrapper);
        
        if (order == null) {
            log.error("订单不存在：{}", orderNo);
            return new R<>(500, "订单不存在", null);
        }

        try {
            //创建HttpClient对象 作用远程请求
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //支持https请求
            httpClient.setHttps(true);
            //设置请求的参数->xml格式
            Map<String, String> param = new HashMap<>();
            param.put("appid", appId);
            param.put("mch_id", mchId);
            param.put("nonce_str", WXPayUtil.generateNonceStr());
            param.put("body", "医院支付-" + order.getPatientName());
            param.put("out_trade_no", orderNo);
            // 固定支付金额为0.01元
            param.put("total_fee", new BigDecimal(0.01).multiply(new BigDecimal(100)).longValue() + "");
            param.put("spbill_create_ip", request.getRemoteAddr());
            param.put("notify_url", notifyUrl);
            param.put("trade_type", "NATIVE");
            
            log.info("支付参数：{}", param);
            
            //设置请求参数
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(param, apiKey));
            //发送请求
            httpClient.post();
            //获取响应结果
            String xml = httpClient.getContent();
            log.info("支付响应：{}", xml);

            Map<String, String> map = WXPayUtil.xmlToMap(xml);
            if ("SUCCESS".equals(map.get("result_code"))) {
                Map<String, Object> result = new HashMap<>();
                //向正常队列发送信息
                rabbitTemplate.convertAndSend("delayed.exchange", "delayed.queue", orderNo);
                result.put("orderId", orderNo);
                result.put("content", map.get("code_url"));
                result.put("totalFee", order.getOrderAmount());
                log.info("支付二维码生成成功：{}", orderNo);
                return new R<Map>(200, "生成二维码成功", result);
            } else {
                log.error("支付二维码生成失败：{}", map.get("err_code_des"));
                return new R<>(500, "生成二维码失败：" + map.get("err_code_des"), null);
            }
        } catch (Exception e) {
            log.error("支付异常", e);
            return new R<>(500, "支付异常：" + e.getMessage(), null);
        }
    }

    @Override
    public R<Map> queryPayStatus(String orderNo) {
        log.info("开始查询支付状态：{}", orderNo);
        try {
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            Map<String, String> params = new HashMap<>();
            params.put("appid", appId);
            params.put("mch_id", mchId);
            params.put("out_trade_no", orderNo);
            params.put("nonce_str", WXPayUtil.generateNonceStr());

            String signedXml = WXPayUtil.generateSignedXml(params, apiKey);
            client.setXmlParam(signedXml);
            client.setHttps(true);
            client.post();

            String content = client.getContent();
            log.info("支付状态查询响应：{}", content);
            
            Map<String, String> responseMap = WXPayUtil.xmlToMap(content);
            
            // 检查返回码
            if (!"SUCCESS".equals(responseMap.get("return_code"))) {
                log.error("支付状态查询失败：{}", responseMap.get("return_msg"));
                return new R<>(500, "查询失败：" + responseMap.get("return_msg"), null);
            }
            
            // 检查业务结果
            if (!"SUCCESS".equals(responseMap.get("result_code"))) {
                log.error("支付状态查询业务失败：{}", responseMap.get("err_code_des"));
                return new R<>(500, "业务失败：" + responseMap.get("err_code_des"), null);
            }

            // 检查交易状态
            if ("SUCCESS".equals(responseMap.get("trade_state"))) {
                // 更新订单状态
                boolean orderUpdated = orderDao.updateOrderStatus(orderNo) > 0;
                boolean itemsUpdated = hisOrderChargeItemDao.updateByRegId(orderNo) > 0;
                List<HisOrderChargeItem> hisOrderChargeItems = hisOrderChargeItemDao.selectByOrderId(orderNo);
                for (HisOrderChargeItem hisOrderChargeItem : hisOrderChargeItems) {
                    careOrderItemDao.updateStatusById(hisOrderChargeItem.getItemId());
                }

                
                if (orderUpdated && itemsUpdated) {
                    log.info("支付成功，订单状态已更新：{}", orderNo);
                    return new R<>(200, "支付成功", responseMap);
                } else {
                    log.error("支付成功但订单状态更新失败：{}", orderNo);
                    return new R<>(500, "订单状态更新失败", null);
                }
            } else if ("NOTPAY".equals(responseMap.get("trade_state"))) {
                log.info("订单未支付：{}", orderNo);
                return new R<>(201, "未支付", responseMap);
            } else {
                log.error("支付异常状态：{}", responseMap.get("trade_state_desc"));
                return new R<>(500, "支付异常：" + responseMap.get("trade_state_desc"), null);
            }
        } catch (Exception e) {
            log.error("支付状态查询异常", e);
            return new R<>(500, "查询异常：" + e.getMessage(), null);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R createOrder(OrderChargeRequestVo orderChargeRequestVo) {
        log.info("开始创建订单：{}", orderChargeRequestVo);
        try {
            HisCareHistory hisCareHistory = orderDao.selectByRegId(orderChargeRequestVo.getOrderChargeDto().getRegId());
            if (hisCareHistory == null) {
                log.error("未找到对应的就诊记录：{}", orderChargeRequestVo.getOrderChargeDto().getRegId());
                return new R<>(500, "未找到对应的就诊记录", null);
            }

            //订单对象
            HisOrderCharge hisOrderCharge = new HisOrderCharge();
            //创建一个list集合，存放订单项的集合
            List<HisOrderChargeItem> hisOrderChargeItemList = orderChargeRequestVo.getOrderChargeItemDtoList();
            //获取其中的病历ID，患者姓名，挂号单号放入hisOrderCharge中
            hisOrderCharge.setChId(hisCareHistory.getChId());
            hisOrderCharge.setPatientName(hisCareHistory.getPatientName());
            hisOrderCharge.setRegId(hisCareHistory.getRegId());
            //生成订单id
            hisOrderCharge.setOrderId("ODC" + SnowflakeIdGenerator.nextId());
            //设置支付状态为0
            hisOrderCharge.setOrderStatus("0");
            //将总费用放入hisOrderCharge中
            hisOrderCharge.setOrderAmount(orderChargeRequestVo.getOrderChargeDto().getOrderAmount());
            String token = request.getHeader("token");
            hisOrderCharge.setCreateBy(userFeign.getUserInfo(token).getData().getUserName());
            hisOrderCharge.setUpdateBy(userFeign.getUserInfo(token).getData().getUserName());
            //设置支付类型
            hisOrderCharge.setPayType("2");
            hisOrderCharge.setCreateTime(new Date());
            hisOrderCharge.setPayTime(new Date());
            hisOrderCharge.setUpdateTime(new Date());

            //存储订单详情
            List<String> ItemIdList = new ArrayList<>();
            for (HisOrderChargeItem item : hisOrderChargeItemList) {
                item.setOrderId(hisOrderCharge.getOrderId());
                item.setStatus("0");
                hisOrderChargeItemDao.insert(item);
                ItemIdList.add(item.getItemId());
            }

            //存储订单
            int i = orderDao.insert(hisOrderCharge);
            if (i > 0) {
                log.info("订单创建成功：{}", hisOrderCharge.getOrderId());
                //向正常队列发送信息
                rabbitTemplate.convertAndSend("delayed.topic.exchange", "delayed.queue", hisOrderCharge.getOrderId());
                return new R<>(200, "订单创建成功", hisOrderCharge.getOrderId());
            }
            log.error("订单创建失败");
            return new R<>(500, "订单创建失败", null);
        } catch (Exception e) {
            log.error("订单创建异常", e);
            throw e;
        }
    }

    //手机微信支付
    @Override
    public R wxPay(String chId) {
        log.info("开始创建手机支付订单，病例ID：{}", chId);
        try {
            //根据病例id查询his_care_order表，得到处方id
            String coId = orderDao.selectCoIdByChId(chId).getCoId();
            //根据病例id查询his_care_history表，得到患者姓名，挂号单号
            HisCareHistory hisCareHistory = orderDao.selectByChId(chId);
            //根据处方id查询his_care_order_item表，得到所有项目信息,是为了生成订单详情表
            List<HisCareOrderItem> hisOrderChargeItems = orderDao.selectByCoId(coId);
            
            //生成新订单
            HisOrderCharge hisOrderCharge = new HisOrderCharge();
            //获取其中的病历ID，患者姓名，挂号单号放入hisOrderCharge中
            hisOrderCharge.setChId(chId);
            hisOrderCharge.setPatientName(hisCareHistory.getPatientName());
            hisOrderCharge.setRegId(hisCareHistory.getRegId());
            //生成订单id
            hisOrderCharge.setOrderId("ODC" + SnowflakeIdGenerator.nextId());
            //设置支付状态为0
            hisOrderCharge.setOrderStatus("0");
            //将总费用放入hisOrderCharge中
            hisOrderCharge.setOrderAmount(1L); // 设置为1分钱
            //设置支付类型
            hisOrderCharge.setPayType("2");
            hisOrderCharge.setCreateTime(new Date());
            hisOrderCharge.setPayTime(new Date());
            hisOrderCharge.setUpdateTime(new Date());
            
            //存储订单
            orderDao.insert(hisOrderCharge);
            //根据病例id查询his_care_order表，
            CareOrder careOrder = careOrdersDao.selectByChId(chId);
            //根据co_id获取his_care_order_item表种的item_id
            List<String> strings = careOrderItemDao.selectItemIdByCoId(careOrder.getCoId());

            int i = 0;

            //存储订单详情
            for (HisCareOrderItem item : hisOrderChargeItems) {
                HisOrderChargeItem hisOrderChargeItem = new HisOrderChargeItem();
                hisOrderChargeItem.setItemId(strings.get(i));
                hisOrderChargeItem.setCoId(careOrder.getCoId());
                hisOrderChargeItem.setItemName(item.getItemName());
                hisOrderChargeItem.setItemPrice(item.getPrice());
                hisOrderChargeItem.setItemNum(item.getNum().intValue());
                hisOrderChargeItem.setItemAmount(item.getAmount().intValue());
                hisOrderChargeItem.setOrderId(hisOrderCharge.getOrderId());
                hisOrderChargeItem.setStatus("0");
                hisOrderChargeItem.setItemType(item.getItemType());
                hisOrderChargeItemDao.insert(hisOrderChargeItem);
                i++;
            }
            //向正常队列发送信息
            rabbitTemplate.convertAndSend("delayed.topic.exchange", "delayed.queue", hisOrderCharge.getOrderId());
            //根据订单号查询出订单信息
            QueryWrapper<HisOrderCharge> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("order_id", hisOrderCharge.getOrderId());
            HisOrderCharge order = orderDao.selectOne(queryWrapper);
            
            if (order != null) {
                //创建HttpClient对象 作用远程请求
                HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
                //支持https请求
                httpClient.setHttps(true);
                //设置请求的参数->xml格式
                Map<String, String> param = new HashMap<>();
                param.put("appid", appId);
                param.put("mch_id", mchId);
                param.put("nonce_str", WXPayUtil.generateNonceStr());
                param.put("body", "医院支付-" + order.getPatientName());
                param.put("out_trade_no", order.getOrderId());
                // 固定支付金额为0.01元
                param.put("total_fee", new BigDecimal(0.01).multiply(new BigDecimal(100)).longValue() + "");
                param.put("spbill_create_ip", request.getRemoteAddr());
                param.put("notify_url", notifyUrl);
                param.put("trade_type", "NATIVE");
                
                log.info("支付参数：{}", param);
                
                //设置请求参数
                httpClient.setXmlParam(WXPayUtil.generateSignedXml(param, apiKey));
                //发送请求
                httpClient.post();
                //获取响应结果
                String xml = httpClient.getContent();
                log.info("支付响应：{}", xml);

                Map<String, String> map = WXPayUtil.xmlToMap(xml);
                if ("SUCCESS".equals(map.get("result_code"))) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("orderNo", order.getOrderId());
                    result.put("codeUrl", map.get("code_url"));
                    result.put("totalFee", 0.01);
                    log.info("支付二维码生成成功：{}", order.getOrderId());
                    return new R<Map>(200, "生成二维码成功", result);
                } else {
                    log.error("支付二维码生成失败：{}", map.get("err_code_des"));
                    return new R<>(500, "生成二维码失败：" + map.get("err_code_des"), null);
                }
            }
            
            return new R<>(500, "订单不存在", null);
        } catch (Exception e) {
            log.error("支付异常", e);
            return new R<>(500, "支付异常：" + e.getMessage(), null);
        }
    }

    @Override
    public R queryWxPayStatus(String orderId) {


        try {
            // 1. 初始化HttpClient（需替换为实际HTTP客户端实现）
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");

            // 2. 封装请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", appId);         // 修正参数名
            params.put("mch_id", mchId);        // 修正参数名
            params.put("out_trade_no", orderId); // 修正参数名
            params.put("nonce_str", WXPayUtil.generateNonceStr()); // 修正方法名

            // 3. 生成签名并转换为XML
            String signedXml = WXPayUtil.generateSignedXml(params, apiKey); // 补充API密钥
            client.setXmlParam(signedXml); // 修正方法名

            // 4. 发送HTTPS请求
            client.setHttps(true); // 明确启用HTTPS
            client.post();         // 需确保实际执行请求

            // 5. 获取响应
            String content = client.getContent();
            System.out.println("响应内容：" + content);
            Map<String, String> responseMap = WXPayUtil.xmlToMap(content);
            if (responseMap.get("trade_state").equals("SUCCESS")){
                //1.修改订单状态
                int i = orderDao.updateOrderStatus(orderId);
                int i1 = hisOrderChargeItemDao.updateByRegId(orderId);
                //修改处方详情表
                //获取处方co_id

                List<HisOrderChargeItem> hisOrderChargeItems = hisOrderChargeItemDao.selectByOrderId(orderId);
                for (HisOrderChargeItem hisOrderChargeItem : hisOrderChargeItems) {
                    careOrderItemDao.updateStatusById(hisOrderChargeItem.getItemId());
                }



                return new R<>(200,"支付成功",responseMap);


            }


        } catch (Exception e) {
            e.printStackTrace(); // 建议记录日志

        }
        return new R<>(500,"未支付",null);
    }

    @Override
    public R updateOrderStatus(String orderNo) {
        orderDao.updateOrderStatus(orderNo);
        hisOrderChargeItemDao.updateByRegId(orderNo);
        return null;
    }
}
